
# ```
#
# 目标数据：
#
# ```
# -*- coding: utf-8 -*-
"""
Created on Sun Sep 21 19:36:25 2025

@author: JIAMIN
"""
"""
MAT文件数据处理脚本
在Spyder中运行，用于解析.mat文件、重采样信号并生成包含元数据和处理后信号的宽表，以及展开宽表
"""

from pathlib import Path
import numpy as np
import pandas as pd
import scipy.io as sio

def analyze_mat_files():
    """批量分析当前目录下的所有.mat文件，生成信息数据表"""
    current_dir = Path("E:\\研究生\\数学建模\\2025研究生题\\数据集\\目标域数据集")  # 使用原始字符串 (r"") 避免转义问题
    records = []

    for file in current_dir.rglob("*.mat"):
        rel_path = file.relative_to(current_dir)

        try:
            mat_data = sio.loadmat(file)
            # 提取非内置变量（过滤掉以 "__" 开头的变量）
            variables = [k for k in mat_data.keys() if not k.startswith("__")]

            for var in variables:
                data = mat_data[var]
                if isinstance(data, np.ndarray):
                    rows = data.shape[0]
                    cols = data.shape[1] if data.ndim > 1 else 1
                    records.append([str(rel_path), var, rows, cols])
                else:
                    records.append([str(rel_path), var, None, None])
        except Exception as e:
            records.append([str(rel_path), f"读取失败: {str(e)}", None, None])

    # 转换为 DataFrame
    df = pd.DataFrame(records, columns=["file", "variable", "samples", "columns"])
    return df

def inspect_specific_file(file_path):
    """查看特定.mat文件的结构"""
    try:
        data = sio.loadmat(file_path)
        print(f"文件 {file_path} 中的变量:")
        print("=" * 50)
        # 显示所有键
        print("所有键值:", data.keys())
        print("\n变量详情:")
        for key in data.keys():
            if not key.startswith("__"):  # 只显示非内置变量
                var_data = data[key]
                print(f"\n变量名: {key}")
                print(f"类型: {type(var_data)}")
                if isinstance(var_data, np.ndarray):
                    print(f"形状: {var_data.shape}")
        return data
    except Exception as e:
        print(f"读取文件出错: {e}")
        return None

def pick_signal_var(mat_dict, stem_upper):
    """从 loadmat 的字典中挑选信号变量名"""
    keys = [k for k in mat_dict.keys() if not k.startswith("__")]
    if not keys:
        return None
    # 1) 优先文件名同名变量（不区分大小写）
    for k in keys:
        if k.upper() == stem_upper:
            return k
    # 2) 其次第一个 ndarray 变量
    for k in keys:
        if isinstance(mat_dict[k], np.ndarray):
            return k
    # 3) 实在不行就返回第一个
    return keys[0]

def ensure_2d_col(a):
    """将数组转换为二维列向量 (n,1)；若为标量则 (1,1)"""
    arr = np.array(a)
    if arr.ndim == 0:
        return arr.reshape(1, 1)
    if arr.ndim == 1:
        return arr.reshape(-1, 1)
    if arr.ndim == 2:
        # 若是 (1,n) 也转为 (n,1)
        if arr.shape[0] == 1 and arr.shape[1] > 1:
            return arr.reshape(-1, 1)
        return arr
    return arr.reshape(-1, 1)

def load_vector(file_path):
    """读取 .mat 文件，返回一维 np.array"""
    mat = sio.loadmat(file_path)
    # 提取变量名：优先与文件名一致，否则取第一个
    keys = [k for k in mat.keys() if not k.startswith("__")]
    if not keys:
        return None
    var_name = next((k for k in keys if k.upper() == file_path.stem.upper()), keys[0])
    arr = np.array(mat[var_name]).reshape(-1)  # 直接扁平化
    return arr


def process_target_domain(TARGET_DIR=None):
    """处理目标域数据集，生成包含信号数据的DataFrame"""
    if TARGET_DIR is None:
        TARGET_DIR = Path("E:\\研究生\\数学建模\\2025研究生题\\数据集\\目标域数据集")  # 使用绝对路径

    records = []

    for f in sorted(TARGET_DIR.glob("*.mat")):
        try:
            mat = sio.loadmat(f)
        except Exception as e:
            print(f"[WARN] 读取失败：{f} | {e}")
            continue

        var_name = pick_signal_var(mat, f.stem.upper())
        if var_name is None:
            print(f"[WARN] 未找到变量：{f}")
            continue

        x = ensure_2d_col(mat[var_name])  # 统一为 (n,1)
        rpm = np.array([[600.0]])  # 统一 RPM（shape 1x1）

        records.append({
            "file": str(f.resolve()),
            "status": None,  # 未知
            "fault_size_inch": np.nan,  # 未知
            "position": None,  # 未知
            "load": np.nan,  # 未知
            "Xtime": x,
            "RPM": rpm
        })

    tgt_df = pd.DataFrame(records, columns=[
        "file", "status", "fault_size_inch", "position", "load", "Xtime", "RPM"
    ])

    print("目标域表维度：", tgt_df.shape)
    return tgt_df


def create_target_long_table(TARGET_DIR=None):
    """创建目标域长表，将信号数据展开为多行"""
    if TARGET_DIR is None:
        TARGET_DIR = Path("E:\\研究生\\数学建模\\2025研究生题\\数据集\\目标域数据集")  # 使用绝对路径

    frames = []
    for f in sorted(TARGET_DIR.glob("*.mat")):
        try:
            x = load_vector(f)
        except Exception as e:
            print(f"[WARN] 读取失败：{f} | {e}")
            continue
        if x is None:
            continue

        # 创建包含每个信号点的DataFrame
        df = pd.DataFrame({
            "file": str(f.resolve()),
            "status": None,
            "fault_size_inch": np.nan,
            "position": None,
            "load": np.nan,
            "Xtime": x,
            "RPM": 600.0
        })

        frames.append(df)

    # 合并所有数据框
    tgt_long = pd.concat(frames, ignore_index=True)

    print("目标域长表维度：", tgt_long.shape)
    return tgt_long


if __name__ == "__main__":
    # 设置目标域数据集路径
    target_dir = Path("E:\\研究生\\数学建模\\2025研究生题\\数据集\\目标域数据集")

    # 1. 批量分析所有MAT文件
    print("===== 批量分析所有MAT文件 =====")
    mat_info_df = analyze_mat_files()
    print(mat_info_df)

    # 保存分析结果
    mat_info_df.to_excel("E:\\研究生\\数学建模\\2025研究生题\\新\\目标文件\\target_mat_files_info.xlsx", index=False)
    mat_info_df.to_csv("E:\\研究生\\数学建模\\2025研究生题\\新\\目标文件\\target_mat_files_info.csv", index=False)
    print("\n分析结果已保存为Excel和CSV文件")

    # 2. 查看特定文件的结构（示例：目标域数据集\A.mat）
    print("\n" + "=" * 50)
    print("===== 查看特定文件结构 =====")
    target_data = inspect_specific_file(target_dir / "A.mat")

    # 3. 处理目标域数据集（宽表）
    print("\n" + "=" * 50)
    print("===== 处理目标域数据集（宽表） =====")
    target_df = process_target_domain(target_dir)
    print(target_df.head())

    # 保存目标域宽表结果
    target_df.to_pickle("E:\\研究生\\数学建模\\2025研究生题\\新\\目标文件\\target_domain_wide.pkl")
    print("\n目标域宽表数据已保存为pickle文件")

    # 4. 创建目标域长表
    print("\n" + "=" * 50)
    print("===== 创建目标域长表 =====")
    target_long_df = create_target_long_table(target_dir)
    print(target_long_df.head())

    # 保存目标域长表结果
    target_long_df.to_pickle("E:\\研究生\\数学建模\\2025研究生题\\新\\目标文件\\target_domain_long.pkl")
    # 保存为CSV文件（不包含索引）
    target_long_df.to_csv('E:\\研究生\\数学建模\\2025研究生题\\新\\目标文件\\target_long_table.csv', index=None)
    print("\n目标域长表数据已保存为pickle和CSV文件")

# ```

